package com.ledim.chat;

import android.text.TextUtils;
import com.ledim.chat.model.BaseSocketMessage;
import com.ledim.chat.model.MessageHeader;
import com.ledim.utils.LogUtil;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;

public class SocketConnection {

    private Socket mSocket;
    private InputStream mIn;
    private OutputStream mOut;
    private String mServer;
    private int mPort;
    /** 最后心跳时间 **/
    private long mLastBeatTime = 0;
    /** header数据 **/
    private byte[] mHdata = new byte[MessageHeader.LENGTH];

    /**
     * 设置服务器地址
     *
     * @param server
     */
    public synchronized void setServer(String server) {
        String[] str = getHostAndPort(server);
        if (str != null) {
            mServer = str[0];
            mPort = Integer.valueOf(str[1]);
        }
    }

    /**
     * 连接
     */
    public synchronized void connect() {
        if (TextUtils.isEmpty(mServer) || mPort <= 0) {
            LogUtil.e(ConnectionManager.TAG, "聊天室连接失败 mServer=" + mServer + ",mPort=" + mPort);
            return;
        }

        //已经链接，需要关闭
        if (mSocket != null) {
            LogUtil.e(ConnectionManager.TAG, "Socket不为空 先关闭Socket");
            close();
        }

        try {
            LogUtil.e(ConnectionManager.TAG, "Socket开始连接 mServer=" + mServer + ",mPort=" + mPort);
            mSocket = new Socket();
            mSocket.connect(new InetSocketAddress(mServer, mPort));
            mIn = mSocket.getInputStream();
            mOut = mSocket.getOutputStream();

            mLastBeatTime = System.currentTimeMillis();
        } catch (IOException e) {
            LogUtil.e(ConnectionManager.TAG, "聊天室连接失败 e=" + e.getMessage());
        }
    }

    /**
     * 读取消息
     *
     * @return
     */
    public BaseSocketMessage readMessage() {
        try {
            if (mSocket != null && !mSocket.isClosed() && !mSocket.isInputShutdown()) {
                int length = mIn.read(mHdata);
                if (length != MessageHeader.LENGTH) {
                    throw new IOException("包头数据不完整");
                }
                BaseSocketMessage message = BaseSocketMessage.getMsgByHeadData(mHdata);
                if (message.header == null) {
                    LogUtil.e(ConnectionManager.TAG, "包头数据不完整");
                    throw new IOException("包头数据不完整");
                }
                //避免len过大，限制2*1024内 最多
                if (message.header.len > 0 && message.header.len < 1024 * 2) {
                    byte[] hbody = new byte[message.header.len];
                    if (mIn.read(hbody) != message.header.len) {
                        LogUtil.e(ConnectionManager.TAG, "包体数据不完整");
                        throw new IOException("包体数据不完整");
                    }
                    message.parseBody(hbody);
                }
                return message;
            }
        } catch (IOException e) {
        }
        return null;
    }

    /**
     * 是否已连接
     */
    public boolean isConnect() {
        if (mSocket != null) {
            return mSocket.isConnected();
        }
        return false;
    }

    /**
     * 发送消息
     *
     * @param msg
     */
    private void send(byte[] msg) throws IOException {
        mLastBeatTime = System.currentTimeMillis();
        if (msg != null) {
            mOut.write(msg);
        }
        mOut.flush();
    }

    /**
     * 发送消息
     */
    public synchronized void sendMessage(byte[] msg) throws IOException {
        send(msg);
    }

    /**
     * 请求响应
     *
     * @return
     *
     * @throws IOException
     */
    private BaseSocketMessage readAck() throws IOException {
        byte[] hdata = new byte[MessageHeader.LENGTH];
        if (mIn.read(hdata) != MessageHeader.LENGTH) {
            throw new IOException("包头数据不完整");
        }
        BaseSocketMessage message = BaseSocketMessage.getMsgByHeadData(hdata);
        if (message.header == null) {
            throw new IOException("包头数据不完整");
        }
        if (message.header.len > 0) {
            byte[] hbody = new byte[message.header.len];
            if (mIn.read(hbody, MessageHeader.LENGTH, message.header.len) != message.header.len) {
                throw new IOException("包体数据不完整");
            }
            message.parseBody(hbody);
        }
        return message;
    }

    /**
     * 关闭连接
     */
    public void close() {
        try {
            if (mSocket != null) {
                mSocket.close();
            }
            if (mIn != null) {
                mIn.close();
            }
            if (mOut != null) {
                mOut.close();
            }
        } catch (IOException e) {
            LogUtil.e(ConnectionManager.TAG, "Socket关闭失败");
        }
    }

    /**
     * 拿到最后的心跳时间
     *
     * @return
     */
    public synchronized long getLastBeatTime() {
        return mLastBeatTime;
    }

    /**
     * 设置最后心跳时间
     *
     * @param time
     */
    public synchronized void setLastBeatTime(long time) {
        this.mLastBeatTime = time;
    }

    private String[] getHostAndPort(String server) {
        if (TextUtils.isEmpty(server)) {
            return null;
        }
        int pos1 = server.indexOf("//");
        int pos2 = server.lastIndexOf(":");
        if (pos2 <= 0 || pos1 > pos2 || (pos2 + 1 >= server.length())) {
            return null;
        }
        String[] str = new String[2];
        str[0] = server.substring(pos1 + 2, pos2);
        str[1] = server.substring(pos2 + 1);
        LogUtil.e("clf", "getHostAndPort str[0]=" + str[0] + ",str[1]=" + str[1]);
        return str;
    }
}
